#ifndef SALMON_STRING_UTILS
#define SALMON_STRING_UTILS

#include <cstddef>
#include <cstdint>
#include <vector>

namespace salmon {

namespace stringtools {

constexpr double phredToLogProb[] = {-1000.0,
                                     -1.58147375341,
                                     -0.996843044008,
                                     -0.695524471332,
                                     -0.507675873697,
                                     -0.380130408066,
                                     -0.289268187202,
                                     -0.222551515973,
                                     -0.172556572914,
                                     -0.134551960289,
                                     -0.105360515658,
                                     -0.0827653026692,
                                     -0.0651741731994,
                                     -0.051418274158,
                                     -0.0406248442216,
                                     -0.0321335740231,
                                     -0.0254397275342,
                                     -0.0201543647612,
                                     -0.0159758692467,
                                     -0.0126691702086,
                                     -0.0100503358535,
                                     -0.00797499827851,
                                     -0.00632956293111,
                                     -0.00502447389099,
                                     -0.00398901726641,
                                     -0.00316728822616,
                                     -0.00251504651118,
                                     -0.00199725550255,
                                     -0.00158615046428,
                                     -0.00125971852411,
                                     -0.00100050033358,
                                     -0.000794643880558,
                                     -0.000631156481835,
                                     -0.000501312869929,
                                     -0.000398186436251,
                                     -0.00031627777656,
                                     -0.000251220196302,
                                     -0.000199546139504,
                                     -0.000158501880005,
                                     -0.000125900466311,
                                     -0.000100005000333,
                                     -7.94359784262e-05,
                                     -6.30977250677e-05,
                                     -5.01199793479e-05,
                                     -3.9811509523e-05,
                                     -3.16232766123e-05,
                                     -2.51191797991e-05,
                                     -1.99528222059e-05,
                                     -1.58490575203e-05,
                                     -1.25893333633e-05,
                                     -1.00000500003e-05,
                                     -7.94331389525e-06,
                                     -6.30959335027e-06,
                                     -5.01188489573e-06,
                                     -3.98107963e-06,
                                     -3.16228266018e-06,
                                     -2.51188958631e-06,
                                     -1.99526430546e-06,
                                     -1.58489444841e-06,
                                     -1.25892620425e-06,
                                     -1.00000050003e-06,
                                     -7.94328550222e-07,
                                     -6.30957543537e-07,
                                     -5.01187359198e-07,
                                     -3.98107249807e-07,
                                     -3.16227815973e-07,
                                     -2.51188674656e-07,
                                     -1.99526251442e-07,
                                     -1.58489331784e-07,
                                     -1.25892549094e-07,
                                     -1.00000004947e-07,
                                     -7.94328265847e-08,
                                     -6.30957364055e-08,
                                     -5.01187246496e-08,
                                     -3.98107178487e-08,
                                     -3.16227771195e-08,
                                     -2.51188646374e-08,
                                     -1.99526233083e-08,
                                     -1.58489320702e-08,
                                     -1.25892541629e-08,
                                     -1.00000001002e-08,
                                     -7.94328239674e-09,
                                     -6.3095734392e-09,
                                     -5.01187237413e-09,
                                     -3.98107170245e-09,
                                     -3.16227766695e-09,
                                     -2.51188647975e-09,
                                     -1.99526229071e-09,
                                     -1.58489321792e-09,
                                     -1.25892540916e-09,
                                     -9.99999972218e-10,
                                     -7.94328270142e-10,
                                     -6.3095739764e-10,
                                     -5.01187202976e-10};
constexpr uint8_t samToTwoBit[] = {
    0, /*A*/ 0, /*C*/ 1, 0, /*G*/ 2, 0, 0, 0, /*T*/ 3, 0, 0, 0, 0, 0, 0, 0};

constexpr char twoBitToChar[] = {'A', 'C', 'G', 'T'};

constexpr uint8_t charToSamEncode[] = {
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 0,  15, 15, 15, 1,  14, 2,  13, 15, 15, 4,  11, 15, 15, 12,
    15, 3,  15, 15, 15, 15, 5,  6,  8,  15, 7,  9,  15, 10, 15, 15, 15, 15, 15,
    15, 15, 1,  15, 2,  15, 15, 15, 4,  15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 8,  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15};

/*
constexpr uint8_t charToSamEncode[] = {
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 1, 14, 2, 13,
    15, 15, 4, 11, 15, 15, 12, 15, 3, 15, 15, 15, 15, 5, 6, 8, 15, 7, 9,
    15, 10, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15};
    */

std::vector<uint8_t> encodeSequenceInSAM(const char* src, size_t len);

/**
   Incomplete: currently only rev for 'ATCG'
 */
constexpr uint8_t encodedRevComp[] = {15, 8,  4,  15, 2,  15, 15, 15,
                                      1,  15, 15, 15, 15, 15, 15, 15};

constexpr char samCodeToChar[] = {
    '=', 'A', 'C', 'M', 'G', 'R', 'S', 'V', 'T', 'W', 'Y', 'H', 'K', 'D', 'B',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N'};

constexpr char charCanon[] = {
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'A', 'N', 'C', 'N', 'N', 'N', 'G', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'T', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'A', 'N', 'C', 'N', 'N', 'N', 'G', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'T', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N'};

constexpr char charRC[] = {
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'T', 'N', 'G', 'N', 'N', 'N', 'C', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'A', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'T', 'N', 'G', 'N', 'N', 'N', 'C', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'A', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N',
    'N'};

enum class strand { forward, reverse };
} // namespace stringtools
} // namespace salmon

#endif // SALMON_STRING_UTILS
